import { TaskExecutor } from './TaskExecutor';
import { TaskEvent, TaskChangeListener, TaskFunction, TaskOptions, TaskResult } from './types';

// 任务提交器 - 提供高级的任务提交和控制接口
export class TaskSubmitter<T = any> {
    private promiseResolvers: Map<
        string,
        {
            resolve: (result: TaskResult) => void;
            reject: (error: Error) => void;
        }
    > = new Map();

    private taskChangeListener: Set<TaskChangeListener<T>> = new Set();

    constructor(private executor: TaskExecutor) {
        this.setupResultHandling();
    }

    /**
     * 提交任务
     * @param name 任务名称
     * @param taskFunction  任务函数
     * @param options
     * @return 任务ID
     */
    public submitOnly<R = T>(
        name: string,
        taskFunction: TaskFunction<R>,
        options: TaskOptions = {}
    ): string {
        return this.executor.submitTask(name, taskFunction, options);
    }

    /**
     * 批量提交任务
     */
    public submitBatch<R = T>(
        tasks: Array<{
            name: string;
            taskFunction: TaskFunction<R>;
            options?: TaskOptions;
        }>
    ): string[] {
        return this.executor.submitBatchTasks(tasks);
    }

    /**
     * 提交任务并等待执行结果
     */
    public async submitAndWait<R = T>(
        name: string,
        taskFunction: TaskFunction<R>,
        options: TaskOptions = {}
    ): Promise<TaskResult<R>> {
        return new Promise(async (resolve, reject) => {
            try {
                const taskId = this.executor.submitTask(name, taskFunction, options);
                // 保存Promise resolver
                this.promiseResolvers.set(taskId, { resolve, reject });
            } catch (error) {
                reject(error);
            }
        });
    }

    /**
     * 批量提交并等待所有结果成功
     */
    public submitBatchAndWait<R = T>(
        tasks: Array<{
            name: string;
            taskFunction: TaskFunction<R>;
            options?: TaskOptions;
        }>
    ): Promise<TaskResult<R>[]> {
        const promises = tasks.map(({ name, taskFunction, options }) =>
            this.submitAndWait(name, taskFunction, options)
        );

        return Promise.all(promises);
    }

    /**
     * 批量提交并等待部分结果（允许部分失败）
     */
    public async submitBatchAndWaitSettled<R = T>(
        tasks: Array<{
            name: string;
            taskFunction: TaskFunction<R>;
            options?: TaskOptions;
        }>
    ): Promise<PromiseSettledResult<TaskResult<R>>[]> {
        const promises = tasks.map(({ name, taskFunction, options }) =>
            this.submitAndWait(name, taskFunction, options)
        );

        return Promise.allSettled(promises);
    }

    /**
     * 提升指定任务到前面执行
     */
    public promoteTasksToFront(taskIds: string[]): void {
        this.executor.promoteTasksToFront(taskIds);
    }

    /**
     * 通过名称提升指定任务到前面执行
     */
    public promoteTasksToFrontByName(taskNames: string[]): void {
        this.executor.promoteTasksToFrontByName(taskNames);
    }

    /**
     * 启动任务处理
     */
    public start(): void {
        this.executor.start();
    }

    public destroy(): void {
        this.promiseResolvers.clear();
        this.taskChangeListener.clear();
        this.executor.removeEventListener('taskStarted', this.handleTaskStarted);
        this.executor.removeEventListener('taskCompleted', this.handleTaskCompleted);
        this.executor.removeEventListener('taskFailed', this.handleTaskFailed);
        this.executor.removeEventListener('taskCancelled', this.handleTaskCancelled);
    }

    /**
     * 暂停任务处理
     */
    public pause(): void {
        this.executor.pause();
    }

    /**
     * 恢复任务处理
     */
    public resume(): void {
        this.executor.resume();
    }

    /**
     * 取消指定任务
     */
    public cancelTask(taskId: string): void {
        this.executor.cancelTask(taskId);
    }

    /**
     * 取消同名任务
     */
    public cancelTasksByName(taskName: string): void {
        this.executor.cancelTasksByName(taskName);
    }

    /**
     * 监听任务状态变化
     */
    public onTaskChange(listener: TaskChangeListener<T>): void {
        this.taskChangeListener.add(listener);
    }

    /**
     * 移除任务状态变化监听器
     */
    public offTaskChange(listener: TaskChangeListener<T>): void {
        this.taskChangeListener.delete(listener);
    }

    // 私有方法
    private emitTaskChange = (event: TaskEvent<T>): void => {
        this.taskChangeListener.forEach((listener) => {
            try {
                listener(event.task);
            } catch (error) {
                console.error('Error in task status change listener:', error);
            }
        });
    };

    private handleTaskStarted = (event: TaskEvent<T>): void => {
        this.emitTaskChange(event);
    };

    private handleTaskCompleted = (event: TaskEvent<T>): void => {
        const resolver = this.promiseResolvers.get(event.task.id);
        if (resolver && event.result) {
            resolver.resolve(event.result);
            this.promiseResolvers.delete(event.task.id);
        }
        this.emitTaskChange(event);
    };

    private handleTaskFailed = (event: TaskEvent<T>): void => {
        const resolver = this.promiseResolvers.get(event.task.id);
        if (resolver) {
            resolver.reject(event.task.error || new Error(`Task ${event.task.id} failed`));
            this.promiseResolvers.delete(event.task.id);
        }
        this.emitTaskChange(event);
    };

    private handleTaskCancelled = (event: TaskEvent<T>): void => {
        const resolver = this.promiseResolvers.get(event.task.id);
        if (resolver) {
            resolver.reject(new Error(`Task ${event.task.id} was cancelled`));
            this.promiseResolvers.delete(event.task.id);
        }
        this.emitTaskChange(event);
    };

    private setupResultHandling(): void {
        // 监听任务开始
        this.executor.addEventListener('taskStarted', this.handleTaskStarted);
        // 监听任务完成
        this.executor.addEventListener('taskCompleted', this.handleTaskCompleted);
        // 监听任务失败
        this.executor.addEventListener('taskFailed', this.handleTaskFailed);
        // 监听任务取消
        this.executor.addEventListener('taskCancelled', this.handleTaskCancelled);
    }
}
